from wormbane.field_of_view import field_of_view
from wormbane.geometry import Box, Vector
from wormbane.Grid import GridSet
from wormbane.Tile import Tile
from heapq import heapify, heappop, heappush
import sys


class Level(object):

    def __init__(self):
        self.size = Vector(79, 22)
        self.bounds = Box(Vector(0, 0), self.size)
        self.tiles = [[Tile((x, y), self) for y in xrange(self.size.y)]
                      for x in xrange(self.size.x)]
        self.rooms = []
        self.monsters = []
        self.time = 0.0
        self.stair_up_tile = None
        self.stair_down_tile = None
        self.num = 1
        self.light = GridSet(self.size)
        self.sight = GridSet(self.size)

    def push_monster(self, monster):
        heappush(self.monsters, (monster.time, monster))
        self.time = self.monsters[0][0]

    def pop_monster(self):
        return heappop(self.monsters)[1]

    def remove_monster(self, monster):
        for i, item in enumerate(self.monsters):
            if item[1] is monster:
                del self.monsters[i]
                heapify(self.monsters)
                return

    def find_tile(self, pos):
        x, y = pos
        try:
            return self.tiles[x][y]
        except IndexError:
            return None

    def update_light_and_sight(self, hero):

        bounds = self.bounds
        tiles = self.tiles
        def visit(grid_set):
            def impl(x, y):
                if (x, y) not in bounds:
                    return True
                grid_set.add((x, y))
                tile = tiles[x][y]
                return (tile.top_item and not tile.top_item.passable
                        or tile.feature and not tile.feature.passable)
            return impl

        x, y = hero.pos
        self.light.clear()
        field_of_view(x, y, 3, visit(self.light))
        self.sight.clear()
        field_of_view(x, y, max(self.size), visit(self.sight))
